package maquinasam.sam;

import java.util.ArrayList;
import java.util.Arrays;

public class Instruccion {
	// Mnemónicos de las instrucciones (lista de opcodes)
	public static final byte INVALID = -1;
	public static final byte LOAD 	= 0;
	public static final byte LOADA 	= 1;
	public static final byte LOADI 	= 2;
	public static final byte LOADL 	= 3;
	public static final byte STORE 	= 4;
	public static final byte STOREI = 5;
	public static final byte CALL 	= 6;
	public static final byte CALLI 	= 7;
	public static final byte RETURN = 8;
	public static final byte PUSH 	= 9;
	public static final byte POP 	= 10;
	public static final byte JUMP 	= 11;
	public static final byte JUMPI 	= 12;
	public static final byte JUMPIF = 13;
	public static final byte HALT 	= 14;

	// Atributos
	private byte opcode; 	// op = Código de operación
	private byte register; 	// r = Id del registro implicado
	private byte size; 		// n = Tamaño del operando
	private byte offset; 	// d = Desplazamiento
	
	private static String[] instrStrings = {  "LOAD", "LOADA", "LOADI", "LOADL",
		"STORE", "STOREI", "CALL", "CALLI", "RETURN", "PUSH", "POP", "JUMP",
		"JUMPI", "JUMPIF", "HALT"};
	
	private static ArrayList<String> instrArray = 
			new ArrayList<String>(Arrays.asList(instrStrings));
	
	public static int getInstrID(String str) {
		return instrArray.indexOf(str);
	}
	
	public static String getInstrStr(int id) {
		return instrStrings[id];
	}
	
	// Constructor
	public Instruccion(byte opcode, byte register, byte size, byte offset) {
		this.opcode = opcode;
		this.register = register;
		this.size = size;
		this.offset = offset;
	}
	
	public Instruccion() {
		this.opcode = INVALID;
		this.register = INVALID;
		this.size = INVALID;
		this.offset = INVALID;
	}
	
	// Getters & Setters
	public byte getOpcode() {
		return opcode;
	}
	
	public void setOpcode(byte opcode) {
		this.opcode = opcode;
	}
	
	public byte getRegister() {
		return register;
	}
	
	public void setRegister(byte register) {
		this.register = register;
	}
	
	public byte getSize() {
		return size;
	}
	
	public void setSize(byte size) {
		this.size = size;
	}
	
	public byte getOffset() {
		return offset;
	}
	
	public void setOffset(byte offset) {
		this.offset = offset;
	}
	
	
	public String toString() {
		String cadena = getInstrStr(this.getOpcode());
		if (this.getSize() > 0)
			cadena += " (" + this.getSize() + ") ";
		
		if (this.getOffset() != INVALID)
			cadena += " " + this.getOffset();
		
		if (this.getRegister() != INVALID)
			cadena += "[" + this.getRegister() + "]";
		
		return cadena; 
	}
}
